package com.ctepl.common.db;

import java.sql.*;
import java.util.*;
//import org.apache.log4j.Logger;

/**
 * Title: DittoResultSet Description: Wrapper for ResultSet class - serves as a
 * disconnected ResultSet without the unnecessary overhead. 
 * Copyright: Copyright (c) 2008, Todd Cook Used by permission. Adapted from Todd Cook's personal code library
 * 
 * Company: www.cookconsulting.com
 * 
 * @author Todd Cook
 * @version 1.1
 */

public class DittoResultSet {

	//static Logger log = Logger.getLogger(DittoResultSet.class);

	private Vector vHeaderNames;

	private Vector vTypes;

	private Vector vNull;

	private Vector vRows;

	final String strSeparator = "|";

	private int iRow = -2;

	private HashMap hmHeaders;

	private String dittoResultSetNullValue = "DittoResultSetNullValue";

	private ResultSet rs;

	/**
	 * <p> Default Constructor
	 * @author Rahul Choudhary
	 */
	public DittoResultSet() {
	}

	/**
	 * @author Rahul Choudhary
	 * @return Ditto Result Set Null Value
	 */
	public String getDittoResultSetNullValue() {
		return dittoResultSetNullValue;
	}

	/**
	 * <p> Set a new default null value for DittoResultSet to return
	 * @author Rahul Choudhary 
	 * @param NewDittoResultSetNullValue
	 */
	public void setDittoResultSetNullValue(String NewDittoResultSetNullValue) {
		if (NewDittoResultSetNullValue != null)
			dittoResultSetNullValue = NewDittoResultSetNullValue;
	}

	/**
	 * <P> Creating a DittoResultSet object by passing a populated Result Set
	 * @author Rahul Choudhary
	 * @param rs 
	 */
	public DittoResultSet(ResultSet rs) {
		try {
			this.rs = rs;
			ResultSetMetaData rsmd = rs.getMetaData();
			int iCol = rsmd.getColumnCount();
			vHeaderNames = new Vector(iCol);
			vTypes = new Vector(iCol);
			vNull = new Vector(iCol);

			hmHeaders = new HashMap(iCol);
			vRows = new Vector();
			for (int ii = 1; ii < iCol + 1; ii++) {
				vTypes.addElement((Object) (rsmd.getColumnTypeName(ii) + "("
						+ rsmd.getColumnDisplaySize(ii) + "."
						+ rsmd.getScale(ii) + ")"));
				vNull
						.addElement((Object) ((rsmd.isNullable(ii) == ResultSetMetaData.columnNoNulls) ? "NOT NULL"
								: ""));
				vHeaderNames.addElement((Object) rsmd.getColumnName(ii));
				hmHeaders.put(rsmd.getColumnName(ii).toUpperCase(),
						new Integer(ii));
			}

			StringBuffer sb;
			Iterator itvHN;
			// can't make an iterator for a hashmap, arg! don't know why...
			String strVal = "";
			while (rs.next()) {
				sb = new StringBuffer();
				itvHN = vHeaderNames.iterator();
				//  for (int ii =1, j = hmHeaders.size(); ii < j; ii++ )
				while (itvHN.hasNext()) {
					String strHeader = (String) itvHN.next();
					// String strHeader = (String) hmHeaders.get(new
					// Integer(ii)); // itvHN.next();
					// log.debug ("strHeader=" + strHeader);
					if (rs.getString(strHeader) != null)
						sb.append(rs.getString(strHeader));
					else {
						sb.append(dittoResultSetNullValue);
					}

					sb.append(strSeparator);
				}
				vRows.addElement((Object) sb.toString());
			}
			iRow = -1; //used in next();
		} catch (SQLException e) {
//			log.error("Error Message"+e.getMessage(),e);
		}
	}

	public void validate() {
	}

	/**
	 * @author Rahul Choudhary
	 * @param iNamePos
	 * @return String value of the column at provided location
	 */
	public String getString(int iNamePos) {
		String strTmp = "";
		try {
			String strPackedRow = (String) vRows.elementAt(iRow);

			StringTokenizer st = new StringTokenizer(strPackedRow, strSeparator);
			int ii = 0;
			while (ii < iNamePos) {
				strTmp = st.nextToken();
				ii++;
			}
		} catch (Exception e) {
	//		log.error("Error Message"+e.getMessage(),e);
			
		}
		return strTmp;
	}

	/**
	 * <P> Not sure why & where this is used???
	 * @author Rahul Choudhary
	 * @param SQLHeaderName
	 * @return
	 */
	public String getString3(String SQLHeaderName) {
		try {
			String val = getString(SQLHeaderName);
			float f = (float) ((int) (1000 * Float.parseFloat(val))) / 1000;
			return Float.toString(f);
		} catch (Exception e) {
		}
		return "0";
	}

	public int getInt(int iNamePos) {
		if (getString(iNamePos) == null)
			return 0;
		else
			return (java.lang.Integer.parseInt(getString(iNamePos)));
	}

	public int getInt(String SQLHeaderName) {
		if (getString(SQLHeaderName) == null || getString(SQLHeaderName).length() == 0)
			return 0;
		else {
			int iRet = 0;
			try {
				iRet = java.lang.Integer.parseInt(getString(SQLHeaderName));
			} catch (Exception e) {
			}
			return iRet;
		}
	}

	
	/**
	 * Surendra - 04/20/2005
	 * 
	 * Used in SearchBean.setBeanInfo() method. 
	 * The DittoResultSet.getInt(SQLHeaderName) method returns a value of '0' if the value of SQLHeaderName 
	 * is 'null'. But in setBeanInfo, we need to know the value of 'hand_setup' i.e., 0 or 1 or null.
	 * This method returns '-1' if value of DittoResultSet.getInt(SQLHeaderName) is 'null'
	 * 
	 * @param SQLHeaderName - header name
	 * @param returnNegativeValue - method to return negative value, if header is not found or null 
	 * @return
	 */
	public int getInt(String SQLHeaderName, boolean returnNegativeValue) {
		if (getString(SQLHeaderName) == null || getString(SQLHeaderName).length() == 0)
			return -1;
		else {
			int iRet = 0;
			try {
				iRet = java.lang.Integer.parseInt(getString(SQLHeaderName));
			} catch (Exception e) {				
				iRet = -1;
			} 
			return iRet;
		}
	}

	public String getString(String SQLHeaderName) {
		String strTmp = "";
		try {

			String strPackedRow = (String) vRows.elementAt(iRow);
			//        log.debug("(hmHeaders.get(SQLHeaderName.toUpperCase() )
			// -->"+hmHeaders.get(SQLHeaderName.toUpperCase()) );
			int iNamePos = Integer.parseInt((hmHeaders.get(SQLHeaderName
					.toUpperCase())).toString());
			// zeesh, how ugly is that!
			StringTokenizer st = new StringTokenizer(strPackedRow, strSeparator);
			int ii = 0;
			while (ii < iNamePos) {
				strTmp = st.nextToken();
				ii++;
			}
		} catch (Exception e) {
		//	log.error("Error Message"+e.getMessage(),e);
			
		}
		// log.debug("strTmp="+strTmp);
		// log.debug("strTmp len="+strTmp.length());
		strTmp = strTmp.trim();
		//     try{
		//    if (strTmp.length() ==1)/
		//       log.debug("strTmp="+ strTmp + " charVal="+ (new
		// Character(strTmp.charAt(0))).charValue() );
		//     }
		//     catch (Exception e)
		//     {log.error("Error Message"+e.getMessage(),e);}

		if (strTmp.equals(dittoResultSetNullValue))
			return null;
		else
			return strTmp;
	}

	public void close() {
		//Should clear out the member values
		//  vHeaderNames.clear();
		vRows.clear();
		iRow = -2;
		hmHeaders.clear();
	}

	public boolean next() {
		if (iRow == -2)
			return false; // should throw exception, means RS not loaded
		if (iRow + 1 == vRows.size())
			return false;
		if (iRow == -1) {
			iRow = 0; // means rs was loaded and it's ready to look at first row
			return true;
		}
		if (iRow == 0) {
			iRow++;
			return true;
		}
		if (iRow == vRows.size())
			return false;
		else {
			iRow++;
			return true;
		}
	}

	public int getNumberOfColumns() {
		return vHeaderNames.size(); // +1 ; // like a zero based 'array'
		//return hmHeaders.size() + 1;
	}

	public int getNumberOfRows() {
		return vRows.size();
	}

	public String getRow(int i) {
		if (i >= vRows.size())
			return "";
		else
			return (String) vRows.elementAt(i);
	}

	public String getHeaderName(int i) {
		return (String) vHeaderNames.elementAt(i);
		//return (String)hmHeaders.get(new Integer(i));
	}

	public String getTypeName(int i) {
		return (String) vTypes.elementAt(i);
	}

	public String getNull(int i) {
		return (String) vNull.elementAt(i);
	}

	public void reset() {
		iRow = -1; //used in next();
	}

	public final static void main(String[] args) {
		// add code to provide white box testing
	}
}